package cn._2dland.video
{
	import cn._2dland.events.VideoEvent;
	import cn._2dland.events.VideoStreamEvent;
	import cn._2dland.net.NetConnectionFactory;
	import cn._2dland.ui.ResizableComponect;
	import cn._2dland.utils.VideoUtils;
	
	import flash.events.Event;
	import flash.events.ProgressEvent;
	import flash.events.TimerEvent;
	import flash.media.Video;
	import flash.net.NetConnection;
	import flash.utils.Timer;

	// 缓冲相关事件
	[Event(name="ready", type="cn._2dland.events.VideoEvent")]
	[Event(name="infoUpdate", type="cn._2dland.events.VideoEvent")]
	[Event(name="progress", type="flash.events.ProgressEvent")]
	[Event(name="complete", type="flash.events.Event")]
	// 播放相关事件
	[Event(name="play", type="cn._2dland.events.VideoEvent")]
	[Event(name="pause", type="cn._2dland.events.VideoEvent")]
	[Event(name="stop", type="cn._2dland.events.VideoEvent")]
	[Event(name="playing", type="cn._2dland.events.VideoEvent")]
	[Event(name="seek", type="cn._2dland.events.VideoEvent")]
	[Event(name="changePart", type="cn._2dland.events.VideoEvent")]

	/**
	 * 视频组件类
	 * @author deadblue
	 */	
	public class VideoComponent extends ResizableComponect
	{
		private var _video:Video;
		private var _bufferTimer:Timer;
		private var _playTimer:Timer;

		private var _conn:NetConnection;
		private var _streams:Array;

		//private var _streamsCount:int = 0;
		private var _duration:Number = 0;
		private var _volumn:Number = VideoUtils.DEFAULT_VOLUMN;
		private var _bufferIndex:int = -1;
		private var _playIndex:int = -1;

		private var _isReady:Boolean = false;
		//private var _isPlaying:Boolean = false;

		public function VideoComponent() {
			super();
			_backgroundColor = 0;

			// 初始化视频组件
			_video = new Video();
			addChild(_video);
			_video.x = 0;
			_video.y = 0;

			setSize(540, 384);

			// 初始化计时器
			_bufferTimer = new Timer(VideoUtils.BUFFER_UPDATE_INTERVAL);
			_bufferTimer.addEventListener(TimerEvent.TIMER, bufferHandler);
			_playTimer = new Timer(VideoUtils.PLAYHEAD_UPDATE_INTERVAL);
			_playTimer.addEventListener(TimerEvent.TIMER, playHandler);

			// 获取连接
			_conn = NetConnectionFactory.getInstance().getNetConnection();
		}

		/** 加载视频 */
		public function load(infos:Array):void {
			if(infos == null) return;

			var vs:VideoStream = null;

			_isReady = false;
			//_isPlaying = false;
			_duration = 0;
			//_streamsCount = infos.length;
			_streams = new Array();

			for(var i:int=0; i<infos.length; i++){
				var info:StreamInfo = infos[i] as StreamInfo;
				if(info == null) continue;
				_duration += info.duration;

				vs = new VideoStream(_conn, info);
				addStreamHandler(vs);
				_streams.push(vs);
			}
			
			// 开始缓冲
			_bufferIndex = 0;
			vs = _streams[_bufferIndex] as VideoStream;
			vs.buffer();
			_bufferTimer.start();
		}

		/** 播放 */
		public function play():void {
			var vs:VideoStream = _streams[_playIndex] as VideoStream;
			if(vs == null) return;

			vs.play();
			_playTimer.start();
			//_isPlaying = true;

			dispatchEvent(new VideoEvent(VideoEvent.PLAY, _playIndex));
		}

		/** 暂停 */
		public function pause():void {
			var vs:VideoStream = _streams[_playIndex] as VideoStream;
			if(vs == null) return;

			vs.pause();
			_playTimer.stop();
			//_isPlaying = false;

			dispatchEvent(new VideoEvent(VideoEvent.PAUSE, _playIndex));
		}

		/** 停止 */
		public function stop():void {
			pause();
			seek(0);
			dispatchEvent(new VideoEvent(VideoEvent.STOP));
		}

		/** 定位 */
		public function seek(time:Number):void {
			var seekPart:int = 0;
			var seekTime:Number = time;

			for(var i:int = 0; i < _streams.length; i++){
				var vs:VideoStream = _streams[i] as VideoStream;
				if(seekTime >= vs.info.duration)
					seekTime -= vs.info.duration;
				else {
					seekPart = i;
					break;
				}
			}

			// 出现跨段的情况，调度分段切换事件
			if(seekPart != _playIndex)
				dispatchEvent(new VideoEvent(VideoEvent.CHANGE_PART, seekPart));

			innerSeek(seekPart, seekTime);

			dispatchEvent(new VideoEvent(VideoEvent.SEEK, seekPart, time));
		}

		/** 跳到特定分段 */
		public function jump(index:int):void {
			if(index == _playIndex) return;

			innerSeek(index, 0);

			// 调度切换分段事件
			dispatchEvent(new VideoEvent(VideoEvent.CHANGE_PART, _playIndex));
		}

		/** 调整宽高比 */		
		public function setAspectRatio(ratio:Number):void {
			if(isNaN(ratio)) ratio = 4 / 3;

			if(_width / _height >= ratio) {
				_video.height = _height;
				_video.width = _height * ratio;

				_video.x = (_width - _video.width) / 2;
				_video.y = 0;
			}
			else {
				_video.width = _width;
				_video.height = _width / ratio;

				_video.x = 0;
				_video.y = (_height - _video.height) / 2;
			}
		}

		/*******************************************************/
		public function get isPlaying():Boolean {
			return _playTimer.running;
		}

		public function get duration():Number {
			return _duration;
		}

		public function get parts():Array {
			var parts:Array = new Array();

			for(var i:int = 0; i < _streams.length; i++){
				var vs:VideoStream = _streams[i] as VideoStream;
				if(vs == null) continue;

				var partObj:Object = new Object();
				partObj.id = i;
				partObj.name = vs.info.partName;
				parts.push(partObj);
			}
			return parts;
		}

		public function set volumn(vol:Number):void {
			_volumn = vol;

			if(_playIndex >= 0){
				var vs:VideoStream = _streams[_playIndex] as VideoStream;
				vs.volumn = _volumn;
			}
		}

		/*******************************************************/
		override public function setSize(width:Number, height:Number):void {
			super.setSize(width, height);

			if(_playIndex < 0){
				_video.width = width;
				_video.height = height;
			}
			else{
				var vs:VideoStream = _streams[_playIndex] as VideoStream;
				setAspectRatio(vs.info.width / vs.info.height);
			}
		}

		/*******************************************************/

		/** 为视频流添加事件监听器 */
		private function addStreamHandler(stream:VideoStream):void {
			stream.addEventListener(VideoStreamEvent.STREAM_READY, streamReadyHandler);
			stream.addEventListener(VideoStreamEvent.STREAM_STOP, streamStopHandler);
		}

		/** 内部seek方法，不调度任何事件 */
		private function innerSeek(partIndex:int, time:Number = 0):void {
			var vs:VideoStream = null;

			// 如果当前正在播放某段视频流，将其暂停
			if(_playIndex >= 0) {
				vs = _streams[_playIndex] as VideoStream;
				vs.pause();
			}

			// 播放新的视频流，并定位到指定时间
			_playIndex = partIndex;
			vs = _streams[_playIndex] as VideoStream;
			if(!vs.info.ready) return;

			vs.seek(time / 1000);
			vs.volumn = _volumn;
			_video.attachNetStream(vs.stream);
			_video.smoothing = vs.info.smooth;
			setAspectRatio(vs.info.width / vs.info.height);

			// 是否需要播放
			if(_playTimer.running) vs.play();
			else vs.pause();
		}

		/*******************************************************/

		/** 缓冲计时器响应函数 */
		protected function bufferHandler(e:TimerEvent):void {
			var bufferedTime:Number = 0;
			var vs:VideoStream = null;

			// 计算已经缓冲的时间
			for(var i:int=0; i<_bufferIndex; i++) {
				vs = _streams[i] as VideoStream;
				if(vs == null) continue;

				bufferedTime += vs.info.duration;
			}
			vs = _streams[_bufferIndex] as VideoStream;
			var percent:Number = vs.percent;
			bufferedTime += vs.info.duration * percent;
			dispatchEvent(new ProgressEvent(ProgressEvent.PROGRESS, false, false, bufferedTime, _duration));

			// 判断当前分段是否缓冲完成
			if(percent == 1){
				vs.removeEventListener(VideoStreamEvent.STREAM_READY, streamReadyHandler);

				_bufferIndex ++;
				if(_bufferIndex >= _streams.length) {
					_bufferTimer.stop();
					dispatchEvent(new VideoEvent(Event.COMPLETE));
				}
				else {
					vs = _streams[_bufferIndex] as VideoStream;
					vs.buffer();
				}
			}
		}

		/** 播放计时器响应函数 */		
		protected function playHandler(e:TimerEvent):void {
			var vs:VideoStream = null;
			var playedTime:Number = 0;

			for(var i:int=0; i<_playIndex; i++) {
				vs = _streams[i] as VideoStream;
				if(vs == null) continue;

				playedTime += vs.info.duration;
			}
			vs = _streams[_playIndex] as VideoStream;
			playedTime += vs.stream.time * 1000;

			dispatchEvent(new VideoEvent(VideoEvent.PLAYING, _playIndex, playedTime));
		}

		/** 视频流准备完成响应函数 */		
		protected function streamReadyHandler(e:VideoStreamEvent):void {
			if(!_isReady){
				_isReady = true;
				jump(0);

				dispatchEvent(new VideoEvent(VideoEvent.READY));
			}

			// 判断视频长度是否需要更新
			var vs:VideoStream  = _streams[_bufferIndex];
			if(vs.info.durationFix != 0){
				_duration += vs.info.durationFix;
				dispatchEvent(new VideoEvent(VideoEvent.INFO_UPDATE));
			}
		}

		/** 视频流播放完成响应函数 */	
		protected function streamStopHandler(e:VideoStreamEvent):void {
			if(_playIndex == _streams.length - 1) {
				stop();
			}
			else {
				jump(_playIndex + 1);
			}
		}
	}
}